package com.heima.article.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.mapper.ArticleConfigMapper;
import com.heima.article.mapper.ArticleContentMapper;
import com.heima.article.mapper.ArticleMapper;
import com.heima.article.service.ArticleFreemarkerService;
import com.heima.article.service.ArticleService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.article.pojos.ApArticleContent;
import com.heima.model.common.constants.ArticleConstants;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.search.dtos.SearchArticleVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, ApArticle> implements ArticleService {

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private ArticleContentMapper articleContentMapper;

    @Autowired
    private ArticleConfigMapper articleConfigMapper;
    @Autowired
    private ArticleFreemarkerService articleFreemarkerService;
    @Autowired
    private RabbitTemplate rabbitTemplate;


    /**
     * 加载首页-加载更多-加载更新 三位一体
     *
     * @param dto  type=1 认为是加载更多，type=2表示加载更新
     * @param type
     * @return
     */
    @Override
    public ResponseResult load(ArticleHomeDto dto, Short type) {
        //1.检验参数
        Integer size = dto.getSize();
        if (size == null || size == 0) {
            size = 10;
        }
        dto.setSize(size);
        if (dto.getTag() == null) {
            dto.setTag(ArticleConstants.DEFAULT_TAG);
        }
        //时间校验
        if (dto.getMaxBehotTime() == null) {
            dto.setMaxBehotTime(new Date());
        }
        if (dto.getMinBehotTime() == null) {
            dto.setMinBehotTime(new Date());
        }

        List<ApArticle> apArticles = articleMapper.loadArticleList(dto, type);
        log.info("查询结果：{}", apArticles);

        //3.返回数据
        return ResponseResult.okResult(apArticles);
    }


    /**
     * 保存三剑客
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public ResponseResult save(ArticleDto dto) {
        //保存或修改文章 判断是否存在文章id
        //补充一些信息
        ApArticle apArticle = new ApArticle();
        BeanUtils.copyProperties(dto, apArticle);
        apArticle.setCreatedTime(new Date());
        if (dto.getId() == null) {
            //新增文章
            //保存
            boolean save = save(apArticle);
            if (!save) {
                throw new RuntimeException("文章保存失败");
            }
            //保存文章配置 TODO
            ApArticleConfig apArticleConfig = new ApArticleConfig();
            apArticleConfig.setArticleId(apArticle.getId());
            apArticleConfig.setIsComment(true);
            apArticleConfig.setIsForward(true);
            apArticleConfig.setIsDown(false);
            apArticleConfig.setIsDelete(false);
            int insert1 = articleConfigMapper.insert(apArticleConfig);
            if (insert1 <= 0) {
                throw new RuntimeException("文章配置保存失败");
            }

            if (StrUtil.isNotBlank(dto.getContent())) {
                //保存文章的内容
                ApArticleContent apArticleContent = new ApArticleContent();
                apArticleContent.setContent(dto.getContent());
                apArticleContent.setArticleId(apArticle.getId());
                int insert = articleContentMapper.insert(apArticleContent);
                if (insert <= 0) {
                    throw new RuntimeException("文章内容保存失败");
                }
            }

        } else {
            //修改文章
            boolean b = updateById(apArticle);
            if (!b) {
                throw new RuntimeException("文章更新失败");
            }
            //更新文章内容
            ApArticleContent apArticleContent = new ApArticleContent();
            apArticleContent.setArticleId(apArticle.getId());
            apArticleContent.setContent(dto.getContent());
            int update = articleContentMapper.update(apArticleContent, Wrappers
                    .<ApArticleContent>lambdaUpdate()
                    .eq(ApArticleContent::getArticleId, apArticle.getId()));
            if (update < 1) {
                throw new RuntimeException("更新文章内容失败");
            }
        }
        log.info("更新文章内容成功,id,{}", apArticle.getId());
        System.out.println("更新文章内容成功,id,{}" + apArticle.getId());

        //-------------------------------------------
        //异步调用 生成静态文件上传到minio中
        articleFreemarkerService.buildArticleToMinio(apArticle, dto.getContent());

        //文章保存成功，通过mq发送消息
        log.info("通过mq发送消息到搜索微服务,更新或新增文档,message:{}", apArticle);
        //组装SearchArticleVo
        SearchArticleVo searchArticleVo = null;
        if (apArticle.getId() != null) {
            searchArticleVo = articleMapper.loadArticle1(apArticle.getId());
        }
        if (searchArticleVo == null){
            throw new RuntimeException("文章不存在");
        }
        //将消息转换成json
        String json = JSON.toJSONString(searchArticleVo);
        Message message = MessageBuilder.withBody(json.getBytes(StandardCharsets.UTF_8))
                .setContentType(MessageProperties.CONTENT_TYPE_JSON)
                .build();
        rabbitTemplate.convertAndSend(ArticleConstants.ARTICLE_ES_SYNC_TOPIC, ArticleConstants.ARTICLE_ES_SYNC_ROUTINGKEY, message);


        //3.返回数据,要不要返回文章id ，因为wmnews表中需要
        return ResponseResult.okResult(apArticle.getId());
    }

}
